using System;
using System.Collections.Generic;
using System.Linq.Expressions;
using FastMapper.Core;
using FastMapper.Helpers;

namespace FastMapper.Configuration
{
    public class TypeMapConfigurator<TSource,TDestination> : ITypeMapConfigurator<TSource,TDestination>
    {
        private readonly IList<IPropertyMapConfigurator> _propertyMapConfigurators = new List<IPropertyMapConfigurator>();
        private readonly TypeInfo _sourceType;
        private readonly TypeInfo _destinationType;

        public TypeMapConfigurator()
        {
            _sourceType = new TypeInfo(typeof(TSource));
            _destinationType = new TypeInfo(typeof(TDestination));
        }

        public ITypeMapConfigurator<TSource, TDestination> ForMember<TMember>(Expression<Func<TDestination,TMember>> destinationMember, Action<IPropertyMapConfigurator<TSource>> destinationMemberConfigurator)
        {
            var destinationMemberInfoNode = destinationMember.GetMemberInfoFromRoot();
            if(destinationMemberInfoNode == null)
                throw new InvalidOperationException();
            var propertyMapConfigurator =
                new PropertyMapConfigurator<TSource>(SourceType,destinationMemberInfoNode);
            _propertyMapConfigurators.Add(propertyMapConfigurator);
            destinationMemberConfigurator(propertyMapConfigurator);
            return this;
        }

        public TypeInfo SourceType
        {
            get { return _sourceType; }
        }
        public TypeInfo DestinationType
        {
            get { return _destinationType; }
        }

        private bool Equals(TypeMapConfigurator<TSource, TDestination> other)
        {
            return SourceType == other.DestinationType && DestinationType == other.DestinationType;
        }

        public override bool Equals(object obj)
        {
            if (ReferenceEquals(null, obj)) return false;
            if (ReferenceEquals(this, obj)) return true;
            if (obj.GetType() != this.GetType()) return false;
            return Equals((TypeMapConfigurator<TSource, TDestination>) obj);
        }

        public override int GetHashCode()
        {
            return SourceType.GetHashCode() ^ DestinationType.GetHashCode();
        }
    }
}